/***************************************************************************
 * $ Id : ast_ami.cpp       2011/08/01 00:00:00
 *
 *        swhors@naver.com
 ***************************************************************************/

//#pragma warning(disable:4786)
//#pragma warning(disable:4503)

#include "config.h"

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>

//#include <constant.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <memory.h>

using namespace std;

#include "constant.h"
#include "ast_ami.h"
#include "ast_peg.h"

#include "CmdBase.h"
#include "CmdJoin.h"
#include "CmdLeave.h"
#include "CmdState.h"
#include "CmdDtmf.h"
#include "CmdFactory.h"

ast_ami::ast_ami()
{
    pData = NULL;
}
ast_ami::~ast_ami()
{
    dealloc_mem();
}

void ast_ami::dealloc_mem()
{
    cmd_type   sCmdType   = cmd_type_unknown;
    event_type sEventType = cmd_event_unknown;

    if( pData )
    {
        sCmdType   = getCmdType();
        sEventType = getEventType();
        if( sCmdType == cmd_type_event )
        {
            switch( sEventType )
            {
                case cmd_event_conf_join:
                    delete ((CCmdJoin *)pData);
                    break;
                case cmd_event_conf_dtmf:
                    delete ((CCmdDtmf *)pData);
                    break;
                case cmd_event_conf_leave:
                    delete ((CCmdLeave *)pData);
                    break;
                case cmd_event_conf_state:
                    delete ((CCmdState *)pData);
                    break;
                case cmd_event_unknown:
                case cmd_event_newcallerid:
                case cmd_event_newaccountcode:
                case cmd_event_extensionstatus:
                case cmd_event_newstate:
                case cmd_event_varset:
                case cmd_event_rtcpsent:
                case cmd_event_hangup:
                case cmd_event_newchannel:
                default:
                    break;
            }
        }
        else
        {
            /* do nothing*/
        }
    }
    else
    {
        /* do nothing */
    }
    pData = NULL;
}

int ast_ami::alloc_mem(cmd_type aCmdType, event_type aEventType )
{
    if( pData != NULL )
    {
        dealloc_mem();
    }
    else
    {
        /* do nothing */
    }

    if( aCmdType == cmd_type_event )
    {
        switch( aEventType )
        {
            case cmd_event_conf_join:
                pData = new CCmdJoin;
                break;
            case cmd_event_conf_dtmf:
                pData = new CCmdDtmf;
                break;
            case cmd_event_conf_leave:
                pData = new CCmdLeave;
                break;
            case cmd_event_conf_state:
                pData = new CCmdState;
                break;
            case cmd_event_unknown:
            default:
                pData = NULL;
                break;
        }
    }
    else
    {
        /* do nothing */
    }

    if( pData )
    {
        return 1;
    }
    else
    {
        /* do nothing */
    }
    return 0;
}

void ast_ami::line_print_dbg( char * aFtmt , ... )
{
    va_list sAp;
    va_start( sAp, aFtmt );
    vprintf( aFtmt, sAp );
    va_end( sAp );
}

event_type ast_ami::getEventType()
{
    event_type sEventType = cmd_event_unknown;
    if( pData )
    {
        sEventType = ((CCmdBase*)pData)->getEventType();
    }
    else
    {
        /* do nothing */
    }
    return sEventType;
}

cmd_type ast_ami::getCmdType()
{
    cmd_type sCmdType = cmd_type_unknown;
    if( pData )
    {
        sCmdType = pData->getCmdType();
    }
    else
    {
        /* do nothing */
    }
    return sCmdType;
}

ast_ami *ast_ami::parse( char * aCommandStr, char ** aEndDataStr )
{
    CCmdFactory sCmdFactory;

    if( pData )
    {
        dealloc_mem();
        pData = NULL;
    }

    pData = sCmdFactory.CreateCmdBase( aCommandStr );

    if( pData )
    {
        goto parse_success;
    }
    else
    {
        goto parse_fail;
    }
parse_success:
    *aEndDataStr = NULL;
    return this;

parse_fail:
    *aEndDataStr = aCommandStr;
    return NULL;
}

ast_ami &ast_ami::operator = ( const ast_ami & aOther )
{
    cmd_type   sCmdType   = cmd_type_unknown;
    event_type sEventType = cmd_event_unknown;

    sCmdType = aOther.pData->getCmdType();
    sEventType = aOther.pData->getEventType();

    if( alloc_mem( sCmdType, sEventType) )
    {
        if( sCmdType == cmd_type_event )
        {
            switch( sEventType )
            {
                case cmd_event_conf_join:
                    *((CCmdJoin*)pData) = *((CCmdJoin*)aOther.pData);
                    break;
                case cmd_event_conf_dtmf:
                    *((CCmdDtmf*)pData) = *((CCmdDtmf*)aOther.pData);
                    break;
                case cmd_event_conf_leave:
                    *((CCmdLeave*)pData) = *((CCmdLeave*)aOther.pData);
                    break;
                case cmd_event_conf_state:
                    *((CCmdState*)pData) = *((CCmdState*)aOther.pData);
                    break;
                default:
                    break;
            }
        }
    }
    return *this;
}

int ast_ami::operator == ( const ast_ami & aOther )
{
    int        sRetCode    = 0;
    cmd_type   sCmdType0   = cmd_type_unknown;
    event_type sEventType0 = cmd_event_unknown;
    cmd_type   sCmdType1   = cmd_type_unknown;
    event_type sEventType1 = cmd_event_unknown;

    sCmdType0   = getCmdType();
    sEventType0 = getEventType();
    sCmdType1   = aOther.pData->getCmdType();
    sEventType1 = aOther.pData->getEventType();

    if( sCmdType0 == sCmdType1 )
    {
        if( sEventType0 == sEventType1 )
        {
            if( sCmdType0 == cmd_type_event )
            {
                switch( sEventType0 )
                {
                    case cmd_event_conf_join:
                        if( *((CCmdJoin*)pData) == *((CCmdJoin*)aOther.pData) )
                        {
                            sRetCode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    case cmd_event_conf_dtmf:
                        if( *((CCmdDtmf*)pData) == *((CCmdDtmf*)aOther.pData) )
                        {
                            sRetCode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    case cmd_event_conf_leave:
                        if( *((CCmdLeave*)pData) ==*((CCmdLeave*)aOther.pData) )
                        {
                            sRetCode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    case cmd_event_conf_state:
                        if( *((CCmdState*)pData) == *((CCmdState*)aOther.pData) )
                        {
                            sRetCode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    default:
                        sRetCode = 1;
                }
            }
        }
    }
    return sRetCode;
}

int ast_ami::operator < ( const ast_ami & aOther )
{
    int        sRetCode    = 0;
    cmd_type   sCmdType0   = cmd_type_unknown;
    event_type sEventType0 = cmd_event_unknown;
    cmd_type   sCmdType1   = cmd_type_unknown;
    event_type sEventType1 = cmd_event_unknown;

    sCmdType0   = getCmdType();
    sEventType0 = getEventType();
    sCmdType1   = aOther.pData->getCmdType();
    sEventType1 = aOther.pData->getEventType();

    if( sCmdType0 < sCmdType1 )
    {
        if( sEventType0 < sEventType1 )
        {
            if( sCmdType0 == cmd_type_event )
            {
                switch( sEventType0 )
                {
                    case cmd_event_conf_join:
                        if( *((CCmdJoin*)pData) < *((CCmdJoin*)aOther.pData) )
                        {
                            sRetCode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    case cmd_event_conf_dtmf:
                        if( *((CCmdDtmf*)pData) < *((CCmdDtmf*)aOther.pData) )
                        {
                            sRetCode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    case cmd_event_conf_leave:
                        if( *((CCmdLeave*)pData) < *((CCmdLeave*)aOther.pData))
                        {
                            sRetCode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    case cmd_event_conf_state:
                        if( *((CCmdState*)pData) < *((CCmdState*)aOther.pData))
                        {
                            sRetCode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    default:
                        sRetCode = 1;
                        break;
                }
            }
            else
            {
                /* do nothing */
            }
        }
        else
        {
            /* do nothing */
        }
    }
    else
    {
        /* do nothing */
    }
    return sRetCode;
}

int ast_ami::operator > ( const ast_ami & aOther )
{
    int        sRetcode    = 0;
    cmd_type   sCmdType0   = cmd_type_unknown;
    event_type sEventType0 = cmd_event_unknown;
    cmd_type   sCmdType1   = cmd_type_unknown;
    event_type sEventType1 = cmd_event_unknown;

    sCmdType0   = getCmdType();
    sEventType0 = getEventType();
    sCmdType1   = aOther.pData->getCmdType();
    sEventType1 = aOther.pData->getEventType();

    if( sCmdType0 < sCmdType1 )
    {
        if( sEventType0 < sEventType1 )
        {
            if( sCmdType0 == cmd_type_event )
            {
                switch( sEventType0 )
                {
                    case cmd_event_conf_join:
                        if( *((CCmdJoin*)pData) > *((CCmdJoin*)aOther.pData) )
                        {
                            sRetcode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    case cmd_event_conf_dtmf:
                        if( *((CCmdDtmf*)pData) > *((CCmdDtmf*)aOther.pData) )
                        {
                            sRetcode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    case cmd_event_conf_leave:
                        if( *((CCmdLeave*)pData) > *((CCmdLeave*)aOther.pData) )
                        {
                            sRetcode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    case cmd_event_conf_state:
                        if( *((CCmdState*)pData) > *((CCmdState*)aOther.pData) )
                        {
                            sRetcode = 1;
                        }
                        else
                        {
                            /* do nothing */
                        }
                        break;
                    default:
                        sRetcode = 1;
                }
            }
            else
            {
                /* do nothing */
            }
        }
        else
        {
            /* do nothing */
        }
    }
    else
    {
        /* do nothing */
    }
    return sRetcode;
}

//////////////////////////////////////////////////////////////////////////////
